package com.demo.core.model.support;

import java.util.ArrayList;
import java.util.List;

/**
 * 邻接列表模型（The Adjacency List Model）
 * 通过树的节点ID和相邻的父节点PID生成一个关系树
 * 该模型适合于Oracle的处理层技术,
 * 适用start with... connect by prior id = pid的形式
 * 
 * @param <T> 对象模型
 * @author ryuu.kk
 */
public class AdjacencyListModel extends SimpleBaseModel implements java.io.Serializable {

	/**
	 * 版本的序列化ID
	 */
	private static final long serialVersionUID = 7701229095255975959L;

	public AdjacencyListModel() {
		//nothing
	}
	
	public AdjacencyListModel(Long id, Long pid) {
		super.setId(id);
		//this.id = id;
		this.pid = pid;
	}
	/**
	 * 树的节点ID
	 * @see Long
	 */
	//private Long id;
	
	/**
	 * 树的根节点ID
	 */
	private Long pid;
	
	/**
	 * 一些非树形结构数据,自身包含附加数据,
	 * 这种附加的数据又是一种可以以树形结构描述的数据(树形数据结构),
	 * 这样从附加数据角度,数据整体也为一种树形可以描述的数据
	 * 但是这种数据造成一个问题,无论是邻接列表模型还是先序遍历树模型都无法描述这种主非树-附加数据为树的模型
	 * 只能间接的将附加数据的父子主键作为主数据的父子主键,由originalId记录原始数据的主键id.这样,操作树结构时,使用id-pid
	 * 操作原始数据时,使用这个originalId。
	 * 当originalId为空时,将返回id
	 * 
	 */
	private Long originalId;
	
	/**
	 * 节点名称
	 */
	private String name;
	
	/**
	 * 功能树深度
	 */
	private int depth;
	/**
	 * 对象模型
	 */
	private AdjacencyListModel t;
	/**
	 * 对象模型List
	 */
	private List<AdjacencyListModel> tList;
	
	public Long getPid() {
		return pid;
	}
	public void setPid(Long pid) {
		this.pid = pid;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getDepth() {
		return depth;
	}
	public void setDepth(int depth) {
		this.depth = depth;
	}
	public Long getOriginalId() {
		if (originalId == null) {
			return super.getId();
		}
		return originalId;
	}
	public void setOriginalId(Long originalId) {
		this.originalId = originalId;
	}

	/**
	 * 设置上级树
	 * @param t 模型
	 */
	public void setParent(AdjacencyListModel t) {
		this.t = t;
	}
	/**
	 * 父级树
	 * 从子节点回溯维度考虑
	 */
	public AdjacencyListModel getParent() {
		return this.t;
	}
	public void setChilds(List<AdjacencyListModel> tList) {
		this.tList = tList;
	}
	/**
	 * 加入子节点
	 * @param t 节点
	 */
	public void addChild(AdjacencyListModel t) {
		if (tList == null) {
			tList = new ArrayList<AdjacencyListModel>();
		}
		this.tList.add(t);
	}
	/**
	 * 子级树
	 * 从父级下探维度考虑
	 */
	public List<AdjacencyListModel> getChilds() {
		return this.tList;
	}
	
	/**
	 * 是否是叶子节点
	 * @return true:叶子节点
	 */
	public boolean isLeaf() {
		return (tList == null || tList.size() == 0);
	}
	/**
	 * 是否为根节点
	 * @return true：根节点
	 */
	public boolean isRoot() {
		return this.getParent() == null;
	}
	/**
	 * 当前节点作为根节点的所有叶子节点个数
	 * @return 叶子节点个数
	 */
	public int leafCount() {
		if (tList == null || tList.size() == 0) {
			return 0;
		}
		return count(this);
	}
	
	private int count(AdjacencyListModel node) {
		int count = 0;
		List<AdjacencyListModel> childs = node.getChilds();
		if (node == null || childs == null) {
			return 0;
		}
		for (AdjacencyListModel c : childs) {
			count += count(c);
		}
		return count + childs.size();
	}
	
	/**
	 * 为HashMap或Cache等提供HashCode
	 */
	@Override
	public int hashCode() {
		return super.hashCode();
	}
	
	@Override
	public boolean equals(Object obj) {
		
		if (obj instanceof AdjacencyListModel) {
			AdjacencyListModel mode = (AdjacencyListModel) obj;
			
			if (mode.getId() != null && super.getId().equals(mode.getId())) {
				if ((mode.getPid() == null && this.pid == null) 
						|| mode.getPid().equals(this.pid)) {
					return true;
				}
			}
		}
		return false;
	}
}
